package com.brush.pig.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.brush.common.constant.CacheConstants;
import com.brush.common.exception.database.PrimaryKeyException;
import com.brush.common.exception.database.RecordNotFoundException;
import com.brush.common.utils.SecurityUtils;
import com.brush.pig.domain.IotTask;
import com.brush.pig.domain.req.task.IotTaskAddReq;
import com.brush.pig.domain.req.task.IotTaskEditReq;
import com.brush.pig.domain.req.task.IotTaskReq;
import com.brush.pig.domain.resp.task.IotTaskResp;
import com.brush.pig.service.IotTaskService;
import com.brush.pig.mapper.IotTaskMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Objects;

/**
* @author ckq
* @description 针对表【iot_task(任务)】的数据库操作Service实现
* @createDate 2024-11-13 09:03:42
*/
@Service
public class IotTaskServiceImpl extends ServiceImpl<IotTaskMapper, IotTask>
    implements IotTaskService{


    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public PageInfo<IotTaskResp> pagination(IotTaskReq req) {
        return PageHelper.startPage(req.getPageNum(),req.getPageSize()).doSelectPageInfo(()->{
            this.baseMapper.pagination(req);
        });
    }

    @Override
    public boolean add(IotTaskAddReq req) {

        IotTask task = new IotTask();

        BeanUtils.copyProperties(req,task);

        task.setCreatedBy(SecurityUtils.getUserId());
        task.setUpdatedBy(SecurityUtils.getUserId());

        task.setCreatedTime(new Date());

        boolean result = this.save(task);
        if(result){
            //清除redis缓存
            redisTemplate.opsForValue().set(CacheConstants.TASK_KEY+task.getName(),task);
        }
        return result;


    }

    @Override
    public IotTaskResp findById(Long id) {
        //验证主键是否存在
        if(Objects.isNull(id)){
            throw new PrimaryKeyException();
        }
        //根据id查询任务详情
        IotTask db = this.getById(id);
        //数据库找不到数据
        if(Objects.isNull(db)){
            throw new RecordNotFoundException();
        }
        //封装成返回对象
        IotTaskResp resp = new IotTaskResp();
        BeanUtils.copyProperties(db,resp);
        return resp;
    }

    @Override
    public boolean edit(IotTaskEditReq req) {
        //根据主键id查询
        IotTask db = this.getById(req.getId());
        if(Objects.isNull(db)){
            throw new RecordNotFoundException();
        }

        BeanUtils.copyProperties(req,db);
        boolean result = this.updateById(db);
        if(result){
            //清除redis缓存
            redisTemplate.opsForValue().set(CacheConstants.TASK_KEY+db.getName(),db);
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteById(Long[] ids) {
        if(Objects.isNull(ids) || ids.length==0){
            throw new PrimaryKeyException();
        }

        final IotTaskServiceImpl iotTaskService = this;

        this.redisTemplate.execute(new SessionCallback<Void>() {
            @Override
            public Void execute(RedisOperations operations) throws DataAccessException {
                //开启redis事务
                operations.multi();
                //循环删除数据库数据，时间复杂度：O(n)，事务问题
                try{
                    for(Long id:ids){
                        IotTask db = iotTaskService.getById(id);
                        //数据库找到数据
                        if(Objects.nonNull(db)){
                            //删除数据库中的值
                            iotTaskService.removeById(id);
                            //移除缓存中的值
                            String redisKey = CacheConstants.TASK_KEY+db.getName();
                            operations.delete(redisKey);
                        }
                    }
                    // 提交redis事务
                    operations.exec();
                }catch(Exception e){
                    // 回滚redis事务
                    operations.discard();
                    throw e;
                }
                return null;
            }
        });

        return true;
    }
}




